package momo.app.comms;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Vector;

import momo.app.structure.Peer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class RcvListener extends Thread
{
private Log log = LogFactory.getLog(RcvListener.class);
	
	private ServerSocket server;
	private int port;
	private Vector<RcvChannel> vec;
	
	private final int TIMEOUT = 5 * 60 * 1000;
	private boolean isListening;
	
	public RcvListener(int port)
	{
		this.port = port;
		isListening = true;
		vec = new Vector<RcvChannel>();
		this.start();
	}
	
	public void run()
	{
		if ( log.isDebugEnabled() )
			log.debug("Rcv Server starts");
		try
		{
			server = new ServerSocket();
//			server.bind(new InetSocketAddress(InetAddress.getByName(Config.getIPAddress()), port));
			server.bind(new InetSocketAddress(port));
			server.setSoTimeout(TIMEOUT);
			
			while ( isListening )
			{
				try
				{
					Socket sock = null;
					while( (sock = server.accept()) != null ) 
					{
						vec.add(new RcvChannel(sock));
					}
				}catch(SocketTimeoutException ste)
				{
					if ( log.isDebugEnabled() )
						log.debug("SocketTimeoutException", ste);
				}catch(Exception e)
				{
					if ( log.isErrorEnabled() )
						log.error("Exception", e);
					stopListening();
				}
			}
		}catch(Exception e)
		{
			if ( log.isErrorEnabled() )
				log.error("Exception", e);
			stopListening();
		}
		
		if ( log.isDebugEnabled() )
			log.debug("Rcv Server ends");
	}
	
	public void stopListening()
	{
		isListening = false;
		removeAllChannels();
		try
		{
			server.close();
		}catch (Exception e) {
			if ( log.isErrorEnabled() )
				log.error("Exception", e);
		}
	}
	
	public void removeAllChannels()
	{
		Iterator<RcvChannel> iter = vec.iterator();
		while ( iter.hasNext() )
			iter.next().stopRcving();
		vec.clear();
	}
	
	public boolean removeChannel(Peer peer)
	{
		Iterator<RcvChannel> iter = vec.iterator();
		while ( iter.hasNext() )
		{
			RcvChannel channel = iter.next();
			if ( channel.isSameAssociatedPeer(peer) )
			{
				channel.stopRcving();
				removeDeadListener();
				
				if ( log.isDebugEnabled() )
					log.debug("Rcv Channel of peer: "+peer.toString()+", being removed");
				
				return true;
			}
		}
		return false;
	}
	
	public void removeDeadListener()
	{
		Vector<RcvChannel> v = new Vector<RcvChannel>();
		
		Iterator<RcvChannel> iter = vec.iterator();
		while ( iter.hasNext() )
		{
			RcvChannel channel = iter.next();
			if ( !channel.isAlive() )
				v.add(channel);
		}
		vec.removeAll(v);
	}
}//end of class RcvListener
